﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data;

namespace OrganicNet
{
    public abstract class Entidad
    {
        /// <summary>
        /// Nombre de la entidad, ej. "Factura"
        /// </summary>
        public string Nombre { get; private set; }

        /// <summary>
        /// Objeto de acceso a datos, de uso interno
        /// </summary>
        protected AccesoDatos AD { get; private set; }

        /// <summary>
        /// Nombre de la clave primaria
        /// </summary>
        public string NombrePK { get; private set; }

        /// <summary>
        /// Evento para informar sobre el cambio en cualquier propiedad de la entidad
        /// </summary>
        public event PropertyChangedEvent PropertyChanged;

        /// <summary>
        /// Constructor: recibe información básica de la entidad
        /// </summary>
        /// <param name="nombre"></param>
        public Entidad(string nombre, AccesoDatos ad)
        {
            this.Nombre = nombre;
            this.AD = ad;
        }

        /// <summary>
        /// Asigna la clave primaria forzando la lectura del objeto
        /// (en esta implementacion de ejemplo no utiliza Lazy Loading)
        /// </summary>
        public void InyectarClavePrimaria( object clave) 
        {
            // este método 
            using (IDataReader rd = this.AD.ObtenerDataReader(clave))
            {
                if (!rd.Read())
                    throw new ApplicationException(
                        String.Format("No existen datos de {0} '{1}'", this.Nombre, clave));

                this.CompletarDatos(rd);
            }
        }

        #region Métodos abstractos o virtuales a implementar en cada entidad (hooks)
        public abstract void CompletarDatos(IDataReader reader);
        public abstract void Guardar();
        public virtual bool Validar() { return true; }
        #endregion

        #region Métodos auxiliares
        /// <summary>
        /// Método auxiliar para attachar el debugger de Visual Studio
        /// </summary>
        public void Debug()
        {
            if (!System.Diagnostics.Debugger.IsAttached)
                System.Diagnostics.Debugger.Launch();
        }

        /// <summary>
        /// Lanza el evento de cambio en alguna de las propiedades
        /// </summary>
        protected void RaisePropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        #endregion

    }
}
